<?php
namespace sys;

class ApiDoc{
    private $mainRegex = '/(\/\*\*.*?\@api*\s.*?\*\/\s*(public|private|protected)?\s*function\s+.*?\s*?\()/s';
    protected $documentPath;
    public function __construct($documentPath,$savePath=null){
        $this->documentPath = $documentPath;
        if($savePath == null){
            $this->savePath = getcwd().DIRECTORY_SEPARATOR;
        }else{
            $this->savePath = $savePath;
        }
    }
    /**
     * 开始执行生成
     * @param bool $fetch 是否直接实时输出，默认true，否则生成文件。
     */
    public function make($fetch=true){
		
        if (!is_dir($this->documentPath)) {
            return false;
        }
        $List = $this->getFileList($this->documentPath);
		$Class = [];
		foreach($List as $Path){
			$Path = str_replace('\\','/',$Path);
            $Data = file_get_contents($Path);
			preg_match('/app\/(.*?)\/controller/', $Path, $Matches);
			if(!isset($Matches[1])){continue;}
			$Module = $Matches[1];
        	$Controller = basename($Path,'.php');
            $ApiList = $this->catchEvery($Data);
            foreach ($ApiList as $V) {
                $ApiInfo = $this->parse($V,$Path);
                if($ApiInfo != false){
					$ApiInfo['module'] = $Module;
					$ApiInfo['controller'] = $Controller;
                    $Class[] = $ApiInfo;
                }
            }
        }
		return $Class;
    }

    /**
     * 递归法获取文件夹下文件
     * @param string $Path 路径
     * @param array $fileList 结果保存的变量
     * @param bool $all 可选,true全部,false当前路径下,默认true.
     */
    private function getFileList($Path)
    {
		$FileList = [];
        $List = scandir($Path);
        foreach ($List as $V) {
            if ($V == '.' or $V == '..') {
                continue;
            }
            $TempPath = $Path . DIRECTORY_SEPARATOR . $V;
            $IsDir = is_dir($TempPath);
            $ExtName = substr($V, -4, 4);
            if ($IsDir == false and $ExtName == '.php') {
                $FileList[] = $TempPath;
            } elseif ($IsDir == true) {
                $FileList = array_merge($FileList,$this->getFileList($TempPath));
            }
        }
		return $FileList;
    }
    /**
     * 获取代码文件中所有可以生成api的注释
     * @param string $data 代码文件内容
     */
    private function catchEvery($Data)
    {
        if (!preg_match_all($this->mainRegex, $Data, $Matches)) {
            return [];
        } else {
            return $Matches[1];
        }
    }

    /**
     * 解析每一条可以生成API文档的注释成数组
     * @param string $data 注释文本 catchEvery返回的每个元素
     * @param string $fileName 文件名
     * @return array
     */
    private function parse($Data)
    {
        $Return = [];
		$Temp = '';
		//匹配函数
        preg_match('/(public|private|protected)?\s*function\s+(?<func>.*?)\(/', $Data, $Matches);
        $Return['func'] = !empty($Matches['func']) ? $Matches['func'] : '';
		$Temp = preg_replace('/<method(.*?)}method>/s','',$Data);
		//匹配描述
        preg_match('/\s+\*\s+\@desc\s+(?<desc>.*)?.*/', $Temp, $Matches);
        $Return['desc'] = !empty($Matches['desc']) ? $Matches['desc'] : '';
        preg_match_all('/<method\s+(?<method>.*?){(?<centent>.*?)}method>/s', $Data, $Matches);
		foreach($Matches['method'] as $K => $V){
			$Return['data'][$K] = [
				'name'=>$V
			];
			
		}
		foreach($Matches['centent'] as $K => $V){
			$Return['data'][$K]['params'] = $this->parseParams($V);
			$Return['data'][$K]['return'] = $this->parseReturn($V);
		}
        return $Return;

    }
    private function parseParams($Data){
		$Return = [];
		preg_match_all('/@params{(.*?)}/s', $Data, $Matches);
		foreach($Matches[1] as $K => $V){
			$Return[] = _StrToAttr(trim(trim($V,',')),',',':');
		}
        return $Return;
    }
    private function parseReturn($Data){
		$Return = [];
		preg_match_all('/@return{(.*?)}/s', $Data, $Matches);
		foreach($Matches[1] as $K => $V){
			$Return[] = _StrToAttr(trim(trim($V,',')),',',':');
		}
        return $Return;
    }


}
